import numpy as np
import math
"""
通用规定：
x:输入层向量size(x)=d*1
miu:输入层到隐层的系数矩阵size(miu)=d*q;
alpha:隐层接收到的来自输入层的数据矩阵size(alpha)=q*1，其中alpha.T=x.T*omiga;
gamma:隐层的阈值矩阵size(gamma)=q*1
B:隐层的输出矩阵,size(B)=q*1,其中，B=sigmoid(alpha-gamma)
omiga:隐层到输出层的系数矩阵size(omiga)=q*l
beta:输出层接收到的来自隐层的数据矩阵size(beta)=l*1，其中beta.T=B.T*miu;
theta:输出层的阈值矩阵size(theta)=l*1
ytheo:理论输出矩阵,第k行的理论输出矩阵，size(ythe)=l*1;其中ythe=sigmoid(beta-theta)
yreal:实际输出矩阵，第k行的实际输出矩阵
k:第k个样本
m:样本数量
"""
def sigmoid(x):
    y=1/(1+math.exp(-x))
    return y
def inputtoyin1(x,miu,gamma):
    alpha=x.T*miu
    alpha=alpha.T
    temp=alpha-gamma
    B=[]
    for i in temp:
        b=sigmoid(i)
        B.append(b)
    B=np.mat(B).reshape(np.shape(gamma)[0],1)
    return B
def yin1tooutput(B,omiga,theta):
    beta=B.T*omiga
    beta=beta.T
    temp=beta-theta
    ytheo=[]
    for i in temp:
        y_t=sigmoid(i)
        ytheo.append(y_t)
    ytheo=np.mat(ytheo).reshape(np.shape(theta)[0],1)
    return ytheo
def g(j,ytheo,yreal):
    """
    :param j=1:l
    :param ytheo:
    :param yreal:
    :return:
    """
    g=ytheo[j-1,0]*(1-ytheo[j-1,0])*(yreal[j-1,0]-ytheo[j-1,0])
    return g
def e(h,B,omiga,ytheo,yreal):
    l=np.shape(ytheo)[0]
    sum=0
    for i in range(l):
        temp=omiga[h-1,i]*g(i+1,ytheo,yreal)
        sum=sum+temp
    e=B[h-1]*(1-B[h-1])*sum
    return e
def netrual(X,Yreal,miu,gamma,omiga,theta,yita,times):
    t=0
    m=np.shape(Yreal)[0]
    mi=0
    q=np.shape(omiga)[0]
    l=np.shape(omiga)[1]
    d=np.shape(miu)[0]
    while True:
        if t>times:
            break
        elif mi==m:
            mi=0
        else:
            t=t+1
            B=inputtoyin1(X[mi].T,miu,gamma)
            ytheo=yin1tooutput(B,omiga,theta)
            deltamiu=np.zeros((d,q))
            deltagamma=np.zeros((q,1))
            deltaomiga=np.zeros((q,l))
            deltatheta=np.zeros((l,1))
            for h in range(q):
                for j in range(l):
                    deltaomiga[h,j]=yita*g(j+1,ytheo,Yreal[mi].T)*B[h,0]
            for j in range(l):
                deltatheta[j,0]=-yita*g(j+1,ytheo,Yreal[mi].T)
            for i in range(d):
                for h in range(q):
                    deltamiu[i,h]=yita*e(h+1,B,omiga,ytheo,Yreal[mi].T)*X[mi,i]
            for h in range(q):
                deltagamma[h,0]=-yita*e(h+1,B,omiga,ytheo,Yreal[mi].T)
            miu=miu+deltamiu
            gamma=gamma+deltagamma
            omiga=omiga+deltaomiga
            theta=theta+deltatheta
    return miu,gamma,omiga,theta
X=np.mat([[1,2,3],[4,5,6],[7,8,9]])
Y=np.mat([[10,10],[12,12],[15,13]])
miu=np.mat(np.random.random((3,4)))
gamma=np.mat(np.random.random((4,1)))
omiga=np.mat(np.random.random((4,2)))
theta=np.mat(np.random.random((2,1)))
net=netrual(X,Y,miu,gamma,omiga,theta,0.1,500)
print(net[0])








